//
//  MCNNavItemButton.swift
//  MCNNavItemButton
//
//  Created by yhbj on 2021/9/16.
//

import UIKit

class MCNNavItemButton: UIButton {
    ///是否禁止设置title和attributedTitle
    private(set) var mcn_disableSetTitle: Bool? = false
    ///NavItemBtn的frame更新回调
    var mcn_barItemBtnFrameUpdateBlock: ((_ barItemBtn: MCNNavItemButton) -> ())?
    ///设置NavItemBtn的image颜色
    var mcn_imageColor: UIColor? {
        didSet {
            tintColor = mcn_imageColor
            resetImage()
        }
    }
    ///设置NavItemBtn的tintColor
    var mcn_tintColor: UIColor? {
        didSet {
            tintColor = mcn_tintColor
            resetImage()
            resetTitle()
        }
    }
    ///设置NavItemBtn的tintColor仅用于UIControlStateNormal状态(请在zx_imageColor和zx_tintColor之前设置)，默认为NO
    var mcn_useTintColorOnlyInStateNormal: UIColor?
    ///设置NavItemBtn的字体大小
    var mcn_fontSize: CGFloat = 17 {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            mcn_layoutImageAndTitle()
            noticeUpdateFrame()
        }
    }
    ///禁止自动调整按钮图片和文字的布局，若要使contentEdgeInsets、titleEdgeInsets、imageEdgeInsets等，则需要将此属性设置为NO
    var mcn_disableAutoLayoutImageAndTitle: Bool = true {
        didSet {
            mcn_layoutImageAndTitle()
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn的固定宽度，若设置，则自动计算宽度无效，若要恢复初始值，可设置为-1
    var mcn_fixWidth: CGFloat = 0 {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn的固定高度，若设置，则ZXNavDefalutItemSize无效，若要恢复初始值，可设置为-1
    var mcn_fixHeight: CGFloat = 0 {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn距离左边元素的固定距离，若要恢复初始值，可设置为-1
    var mcn_fixMarginLeft: CGFloat = 0 {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn距离右边元素的固定距离，若要恢复初始值，可设置为-1
    var mcn_fixMarginRight: CGFloat = 0 {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn image的固定大小，若要恢复初始值，可设置为CGSizeZero
    var mcn_fixImageSize: CGSize = .zero {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            mcn_layoutImageAndTitle()
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn文字自动计算宽度后的附加宽度
    var mcn_textAttachWidth: CGFloat = 0 {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            mcn_layoutImageAndTitle()
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn文字的附加高度
    var mcn_textAttachHeight: CGFloat = 0 {
        didSet {
            self.superview?.setValue(1, forKey: "shouldRefLayout")
            mcn_layoutImageAndTitle()
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn的cornerRadius为高度的一半(圆形圆角)
    var mcn_setCornerRadiusRounded: Bool = false {
        didSet {
            noticeUpdateFrame()
        }
    }
    ///设置NavItemBtn内部图片x轴的偏移量，负数代表左移，无title且设置了zx_fixImageSize后生效，仅改变内容imageView的位移，不会改变原始NavItemBtn的frame
    var mcn_imageOffsetX: CGFloat = 0 {
        didSet {
            mcn_layoutImageAndTitle()
        }
    }
    ///设置NavItemBtn的自定义view
    var mcn_customView: UIView? {
        set {
            if newValue == nil {
                guard let oldValue = mcn_customView else { return }
                if subviews.contains(oldValue) {
                    oldValue.removeFromSuperview()
                }
                self.mcn_customView = nil
                noticeUpdateFrame()
                return
            }
            self.mcn_customView = newValue
            if !(subviews.contains(mcn_customView!)) {
                addSubview(mcn_customView!)
            }
            if mcn_customView?.frame == .zero {
                let customViewWidth = mcn_fixWidth < 0 ? MCNNavDefaultItemSize : mcn_fixWidth
                let customViewHeight = mcn_fixHeight < 0 ? MCNNavDefaultItemSize : mcn_fixWidth
                mcn_customView?.frame = CGRect(x: 0, y: 0, width: customViewWidth, height: customViewHeight)
            }
            if mcn_customView!.mcn_width > 0 {
                mcn_fixWidth = mcn_customView!.mcn_width + mcn_customView!.mcn_x * 2
            }
            if mcn_customView!.mcn_height > 0 {
                mcn_fixHeight = mcn_customView!.mcn_height + mcn_customView!.mcn_y * 2
            }
            setImage(nil, for: .normal)
            setTitle("", for: .normal)
            setAttributedTitle(nil, for: .normal)
        }
        get {
            return self.mcn_customView
        }
    }
    ///NavItemBtn frame发生改变时的回调，可在这个block中return修改后的frame
    var mcn_handleFrameBlock: ((_ oldFrame: CGRect) -> (CGRect))?
    ///开始点击的回调
    var mcn_touchesBeganBlock: (() -> ())?
    ///结束点击的回调
    var mcn_touchesEndBlock: (() -> ())?
    
    /// NavItemBtn frame发生改变时的回调
    private var mcn_frameUpdateBlock: ((_ frame: CGRect) -> ())?
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setUp()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUp()
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        setUp()
    }
    
    private func setUp() {
        mcn_fixWidth = -1
        mcn_fixHeight = -1
        mcn_fixMarginLeft = -1
        mcn_fixMarginRight = -1
        mcn_fixImageSize = .zero
    }
    
    //MARK: - public
    ///手动更新布局，一般内部会自动调用，用于高度定制时无法自动更新布局时调用
    func mcn_updateLayout() {
        mcn_layoutImageAndTitle()
        noticeUpdateFrame()
    }
    
    //MARK: - setter
    override func setTitle(_ title: String?, for state: UIControl.State) {
        if mcn_customView != nil && title != nil && title!.count > 0 {
            return
        }
        super.setTitle(title, for: state)
        if mcn_tintColor != nil {
            setTitleColor(mcn_tintColor, for: state)
            mcn_layoutImageAndTitle()
            noticeUpdateFrame()
        }
    }
    
    override func setAttributedTitle(_ title: NSAttributedString?, for state: UIControl.State) {
        if mcn_customView != nil && title != nil && title!.length > 0 {
            return
        }
        super.setAttributedTitle(title, for: state)
        mcn_layoutImageAndTitle()
        noticeUpdateFrame()
    }
    
    override func setImage(_ image: UIImage?, for state: UIControl.State) {
        if mcn_customView != nil && image != nil {
            return
        }
        var tempImage: UIImage?
        if mcn_tintColor != nil {
            tempImage = image?.withRenderingMode(.alwaysTemplate)
        } else {
            tempImage = image?.withRenderingMode(.alwaysOriginal)
        }
        super.setImage(tempImage, for: state)
        if tempImage != nil {
            imageView?.image = image
        }
        mcn_layoutImageAndTitle()
        noticeUpdateFrame()
    }
    
    private func noticeUpdateFrame() {
        if mcn_barItemBtnFrameUpdateBlock != nil {
            mcn_barItemBtnFrameUpdateBlock!(self)
        }
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        mcn_layoutImageAndTitle()
    }
    
    private func resetImage() {
        var isStateFocused = false
        if #available(iOS 9.0, *) {
            isStateFocused = state == .focused
        }
        if mcn_useTintColorOnlyInStateNormal != nil || isStateFocused {
            setImage(image(for: .normal), for: .normal)
        } else {
            setImage(currentImage, for: state)
        }
    }
    
    private func resetTitle() {
        var isStateFocused = false
        if #available(iOS 9.0, *) {
            isStateFocused = state == .focused
        }
        if mcn_useTintColorOnlyInStateNormal != nil || isStateFocused {
            setTitle(title(for: .normal), for: .normal)
        } else {
            setTitle(currentTitle, for: state)
        }
    }
    
    ///刷新NavItemBtn的image和title布局，一般内部会自动调用
    func mcn_layoutImageAndTitle() {
        if mcn_disableAutoLayoutImageAndTitle {
            return
        }
        var btnW = CGFloat(0)
        if currentAttributedTitle != nil {
            btnW = (currentAttributedTitle?.mcn_getAttrRectWidth(limitH: mcn_height, fontSize: (titleLabel?.font.pointSize)!))! + 5.0
        } else {
            if currentTitle != nil && currentTitle!.count > 0 {
                let cTitle = NSString.init(string: currentTitle!)
                btnW = (cTitle.mcn_getRectWidth(limitH: mcn_height, fontSize: (titleLabel?.font.pointSize)!)) + 5.0
            }
        }
        btnW += mcn_textAttachWidth
        if imageView?.image != nil {
            var useFixImageSize = false
            var imageHeight = frame.height
            var imageWidth = frame.height
            if mcn_fixImageSize == .zero {
                imageWidth = mcn_fixImageSize.width
                imageHeight = mcn_fixImageSize.height
                useFixImageSize = true
            }
            var imageViewX = CGFloat(0)
            if ((currentTitle != nil && currentTitle!.count > 0) || (currentAttributedTitle != nil && currentAttributedTitle!.length > 0)) && useFixImageSize {
                imageViewX = (frame.width - imageWidth) / 2 + mcn_imageOffsetX
            }
            imageView?.frame = CGRect(x: imageViewX, y: (frame.height - imageHeight) / 2, width: imageWidth, height: imageHeight)
            titleLabel?.frame = CGRect(x: imageView?.mcn_top ?? 0, y: 0, width: btnW, height: frame.height)
        } else {
            imageView?.frame = .zero
            titleLabel?.frame = CGRect(x: 0, y: 0, width: btnW, height: frame.height)
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        if mcn_touchesBeganBlock != nil {
            mcn_touchesBeganBlock!()
        }
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        if mcn_touchesEndBlock != nil {
            mcn_touchesEndBlock!()
        }
    }
}
